/*
===========================================================================
Copyright (C) 2004-2006 Tony J. White

This file is part of Tremulous.

Tremulous is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.

Tremulous is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with Tremulous; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
===========================================================================
*/

#ifndef _G_ADMIN_H
#define _G_ADMIN_H

#define AP(x) trap_SendServerCommand(-1, x)
#define CP(x) trap_SendServerCommand(ent-g_entities, x)
#define CPx(x, y) trap_SendServerCommand(x, y)
#define ADMP(x) G_admin_print(ent, x)
#define ADMBP(x) G_admin_buffer_print(ent, x)
#define ADMBP_begin() G_admin_buffer_begin()
#define ADMBP_end() G_admin_buffer_end(ent)

#define MAX_ADMIN_LEVELS 32 
#define MAX_ADMIN_ADMINS 1024
#define MAX_ADMIN_BANS 1024
#define MAX_ADMIN_NAMELOGS 128
#define MAX_ADMIN_NAMELOG_NAMES 5
#define MAX_ADMIN_FLAGS 64
#define MAX_ADMIN_COMMANDS 64
#define MAX_ADMIN_CMD_GROUPS 32
#define MAX_ADMIN_CMD_LEN 20
#define MAX_ADMIN_BAN_REASON 50

/*
 * 1 - cannot be vote kicked, vote muted
 * 2 - cannot be censored or flood protected TODO
 * 3 - never loses credits for changing teams
 * 4 - can see team chat as a spectator
 * 5 - can switch teams any time, regardless of balance
 * 6 - does not need to specify a reason for a kick/ban
 * 7 - can call a vote at any time (regardless of a vote being disabled or 
 * voting limitations)
 * 8 - does not need to specify a duration for a ban
 * 9 - can run commands from team chat
 * 0 - inactivity rules do not apply to them
 * ! - admin commands cannot be used on them
 * @ - does not show up as an admin in !listplayers
 * $ - sees all information in !listplayers 
 * # - permanent designated builder
 * ? - sees and can use adminchat
 */
#define ADMF_IMMUNITY '1'
#define ADMF_NOCENSORFLOOD '2' /* TODO */
#define ADMF_TEAMCHANGEFREE '3'
#define ADMF_SPEC_ALLCHAT '4'
#define ADMF_FORCETEAMCHANGE '5'
#define ADMF_UNACCOUNTABLE '6'
#define ADMF_NO_VOTE_LIMIT '7'
#define ADMF_CAN_PERM_BAN '8'
#define ADMF_TEAMCHAT_CMD '9'
#define ADMF_ACTIVITY '0'

#define ADMF_IMMUTABLE '!'
#define ADMF_INCOGNITO '@'
#define ADMF_SEESFULLLISTPLAYERS '$'
#define ADMF_DBUILDER '#'
#define ADMF_ADMINCHAT '?'

#define MAX_ADMIN_LISTITEMS 20
#define MAX_ADMIN_SHOWBANS 10

// Structure to handle the g_admin.c function calls from the console
// Keyword is the !command you type in
// Handler is the function that is called by the !command
// Groups are the groups this function belongs to
// Function is the !help description
// Syntax is the syntax show in !help
typedef struct
{
  char *keyword;
  qboolean ( * handler ) ( gentity_t *ent, int skiparg );
  char *group;
  char *function;  // used for !help
  char *syntax;  // used for !help
  int  command_number; //used to give permissions based on command number - will be set automatically
}
g_admin_cmd_t;

// Structure that handles the groups for the g_admin_cmd_t's
typedef struct
{
	char* groupname;
	g_admin_cmd_t* members[ MAX_ADMIN_COMMANDS ];
	int num_members;
} g_admin_cmd_group_t;

//Handles the admin.dat file's mapping of groups
//to various commands
//level is the level of the admin (used for the admin hierarchy. Higher is better)
//name is the name of the level (ie 'Server Owner', 'Admin Assist')
//allowed commands is a character array only to save space - it is actually
// an array of numbers corresponding to the functions this level is allowed
// the numbers are dynamically determined at run time
typedef struct g_admin_level
{
  int level;
  char name[ MAX_NAME_LENGTH ];
  g_admin_cmd_t* allowed_commands[ MAX_ADMIN_COMMANDS ];
  int num_allowed_commands;
  char flags[ MAX_ADMIN_FLAGS ];
}
g_admin_level_t;

//Handles the admin.dat file's mapping of players as admins
//GUID is the guid of the player
//name is the player's name
//level is their admin level
//flags are their admin flags
typedef struct g_admin_admin
{
  char guid[ 33 ];
  char name[ MAX_NAME_LENGTH ];
  int level;
  char flags[ MAX_ADMIN_FLAGS ];
}
g_admin_admin_t;

//Structure handling the current bans on the server
typedef struct g_admin_ban
{
  char name[ MAX_NAME_LENGTH ];
  char guid[ 33 ];
  char ip[ 18 ];
  char reason[ MAX_ADMIN_BAN_REASON ];
  char made[ 18 ]; // big enough for strftime() %c
  int expires;
  char banner[ MAX_NAME_LENGTH ];
}
g_admin_ban_t;

//Structure to handle scripts put in the admin.dat file
typedef struct g_admin_script
{
  char command_name[ MAX_ADMIN_CMD_LEN ];
  char exec[ MAX_QPATH ];
  char desc[ 50 ];
  int levels[ MAX_ADMIN_LEVELS + 1 ];
}
g_admin_script_t;

typedef struct g_admin_namelog
{
  char      name[ MAX_ADMIN_NAMELOG_NAMES ][MAX_NAME_LENGTH ];
  char      ip[ 16 ];
  char      guid[ 33 ];
  int       slot;
  qboolean  banned;
}
g_admin_namelog_t;

qboolean G_admin_setup_cmd_groups( void );
qboolean G_admin_ban_check( char *userinfo, char *reason, int rlen );
qboolean G_admin_cmd_check( gentity_t *ent, qboolean say );
qboolean G_admin_readconfig( gentity_t *ent, int skiparg );
qboolean G_admin_flag_permission( gentity_t *ent, char flag );
qboolean G_admin_cmd_permission( gentity_t *ent, g_admin_cmd_t* cmd );
qboolean G_admin_script_permission( gentity_t *ent, g_admin_script_t* script );
qboolean G_admin_name_check( gentity_t *ent, char *name, char *err, int len );
void G_admin_namelog_update( gclient_t *ent, qboolean disconnect );
int G_admin_level( gentity_t *ent );

// ! command functions
qboolean G_admin_time( gentity_t *ent, int skiparg );
qboolean G_admin_setlevel( gentity_t *ent, int skiparg );
qboolean G_admin_kick( gentity_t *ent, int skiparg );
qboolean G_admin_adjustban( gentity_t *ent, int skiparg );
qboolean G_admin_ban( gentity_t *ent, int skiparg );
qboolean G_admin_unban( gentity_t *ent, int skiparg );
qboolean G_admin_putteam( gentity_t *ent, int skiparg );
qboolean G_admin_listadmins( gentity_t *ent, int skiparg );
qboolean G_admin_listlayouts( gentity_t *ent, int skiparg );
qboolean G_admin_listplayers( gentity_t *ent, int skiparg );
qboolean G_admin_map( gentity_t *ent, int skiparg );
qboolean G_admin_devmap( gentity_t *ent, int skiparg );
qboolean G_admin_layoutsave( gentity_t *ent, int skiparg );
qboolean G_admin_mute( gentity_t *ent, int skiparg );
qboolean G_admin_denybuild( gentity_t *ent, int skiparg );
qboolean G_admin_showbans( gentity_t *ent, int skiparg );
qboolean G_admin_showentities( gentity_t *ent, int skiparg );
qboolean G_admin_help( gentity_t *ent, int skiparg );
qboolean G_admin_admintest( gentity_t *ent, int skiparg );
qboolean G_admin_allready( gentity_t *ent, int skiparg );
qboolean G_admin_cancelvote( gentity_t *ent, int skiparg );
qboolean G_admin_passvote( gentity_t *ent, int skiparg );
qboolean G_admin_spec999( gentity_t *ent, int skiparg );
qboolean G_admin_register( gentity_t *ent, int skiparg );
qboolean G_admin_rename( gentity_t *ent, int skiparg );
qboolean G_admin_restart( gentity_t *ent, int skiparg );
qboolean G_admin_nextmap( gentity_t *ent, int skiparg );
qboolean G_admin_namelog( gentity_t *ent, int skiparg );
qboolean G_admin_lock( gentity_t *ent, int skiparg );
qboolean G_admin_unlock( gentity_t *ent, int skiparg );
qboolean G_admin_L1( gentity_t *ent, int skiparg );
qboolean G_admin_info( gentity_t *ent, int skiparg );
void G_admin_info_parse( char *unparsed, char *dest, int maxlength );
qboolean G_admin_putmespec( gentity_t *ent, int skiparg );
qboolean G_admin_warn( gentity_t *ent, int skiparg );
qboolean G_admin_designate( gentity_t *ent, int skiparg );
//Begin Ender code
qboolean G_admin_give( gentity_t *ent, int skiparg );
qboolean G_admin_take( gentity_t *ent, int skiparg );
qboolean G_admin_rcon( gentity_t *ent, int skiparg );
qboolean G_admin_bot( gentity_t *ent, int skiparg );
qboolean G_admin_botlibSetVariable( gentity_t *ent, int skiparg );
qboolean G_admin_botcmd( gentity_t *ent, int skiparg );
qboolean G_admin_setstage( gentity_t *ent, int skiparg );
qboolean G_admin_settime( gentity_t *ent, int skiparg );
qboolean G_admin_playerstats( gentity_t *ent, int skiparg );
qboolean G_admin_toggleinstantbuild( gentity_t *ent, int skiparg );
qboolean G_admin_website( gentity_t *ent, int skiparg );
qboolean G_admin_mumble( gentity_t *ent, int skiparg );
qboolean G_admin_clinic( gentity_t *ent, int skiparg );
qboolean G_admin_xvsall( gentity_t *ent, int skiparg );
qboolean G_admin_report( gentity_t *ent, int skiparg );
qboolean G_admin_layoutload( gentity_t *ent, int skiparg );
qboolean G_admin_layoutdelete( gentity_t *ent, int skiparg );
qboolean G_admin_normalize( gentity_t *ent, int skiparg );
qboolean G_admin_gamestats( gentity_t *ent, int skiparg );
qboolean G_admin_gamestatus( gentity_t *ent, int skiparg );
qboolean G_admin_buildstatus( gentity_t *ent, int skiparg );
//End Ender code
//Begin Champion code :p
qboolean G_admin_listmaps( gentity_t *ent, int skiparg );
qboolean G_admin_setbp( gentity_t *ent, int skiparg );
//End Champion code

void G_admin_print( gentity_t *ent, char *m );
void G_admin_buffer_print( gentity_t *ent, char *m );
void G_admin_buffer_begin( void );
void G_admin_buffer_end( gentity_t *ent );

void G_admin_duration( int secs, char *duration, int dursize );
void G_admin_cleanup( void );
void G_admin_namelog_cleanup( void );

#endif /* ifndef _G_ADMIN_H */
